

package com.lemon.cloud.feign.config;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.lemon.cloud.comm.exception.BusinessException;
import com.lemon.cloud.comm.model.ResultMsg;
import feign.FeignException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.sql.SQLException;
import java.util.List;

import static com.lemon.cloud.comm.model.ResultCode.SERVICE_EXCEPTION;

/**
 * @author Huangds
 * @date 2020-06-29
 */
@Slf4j
@Order(10000)
@RestControllerAdvice
@ConditionalOnExpression("!'${security.oauth2.client.clientId}'.isEmpty()")
public class GlobalBizExceptionHandler {

    /**
     * 全局异常.
     *
     * @param e the e
     * @return R
     */
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResultMsg handleGlobalException(Exception e) {
        log.error("全局异常信息 ex={}", e.getMessage(), e);
        if(e.getCause()!=null && e.getCause().toString().startsWith( "java.sql.SQL" ) ){
            return ResultMsg.resultFail("数据异常，请及时联系管理员");
        }
        // 业务异常交由 sentinel 记录
        //Tracer.trace(e);
        return ResultMsg.resultFail(e.getLocalizedMessage());
    }

    @ExceptionHandler(FeignException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResultMsg handleFeignException(FeignException e) {
        log.error("feign异常信息 ex={}", e.getMessage(), e);
        JSONObject jsonObject = JSONObject.parseObject(e.contentUTF8());
        Integer code = jsonObject.getInteger("code");
        String msg = jsonObject.getString("msg");
        // 业务异常交由 sentinel 记录
        //Tracer.trace(e);
        return StrUtil.isEmpty(msg) ? ResultMsg.resultFail(SERVICE_EXCEPTION)
                : ResultMsg.resultFail((code==null ? SERVICE_EXCEPTION.getCode() : code), msg);

    }

    /**
     * @param exception 参数校验异常
     * @return API返回结果对象包装后的错误输出结果
     */
    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseStatus(HttpStatus.OK)
    public ResultMsg handleIllegalArgumentException(IllegalArgumentException exception) {
        log.error("非法参数,ex = {}", exception.getMessage(), exception);
        return ResultMsg.resultFail("非法参数:"+exception.getMessage());
    }

    /**
     * @param exception 请求方式错误
     * @return API返回结果对象包装后的错误输出结果
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    @ResponseStatus(HttpStatus.OK)
    public ResultMsg handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException exception) {
        log.error("请求方式错误,ex = {}", exception.getMessage(), exception);
        return ResultMsg.resultFail("请求方式错误:"+exception.getMessage());
    }

    /**
     * @param exception 参数校验异常
     * @return API返回结果对象包装后的错误输出结果
     */
    @ExceptionHandler(IllegalStateException.class)
    @ResponseStatus(HttpStatus.OK)
    public ResultMsg handleIllegalStateException(IllegalStateException exception) {
        log.error("非法参数,ex = {}", exception.getMessage(), exception);
        return ResultMsg.resultFail(exception.getMessage());
    }

    /**
     * @param exception 参数校验异常
     * @return 业务异常
     */
    @ExceptionHandler(BusinessException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResultMsg handleBusinessException(BusinessException exception) {
        log.error("业务异常,ex = {}", exception.getMessage(), exception);
        return ResultMsg.resultFail(exception.getMessage());
    }

    /**
     * @param exception 参数校验异常
     * @return 业务异常
     */
    @ExceptionHandler(SQLException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResultMsg handleSQLException(SQLException exception) {
        log.error("SQL异常,ex = {}", exception.getMessage(), exception);
        return ResultMsg.resultFail("数据异常，请及时联系管理员");
    }


    /**
     * validation Exception
     *
     * @param exception
     * @return R
     */
    @ExceptionHandler({MethodArgumentNotValidException.class})
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ResultMsg handleBodyValidException(MethodArgumentNotValidException exception) {
        List<FieldError> fieldErrors = exception.getBindingResult().getFieldErrors();
        log.warn("参数绑定异常,ex = {}", fieldErrors.get(0).getDefaultMessage());
        return ResultMsg.resultFail(fieldErrors.get(0).getDefaultMessage());
    }

    /**
     * validation Exception (以form-data形式传参)
     *
     * @param exception
     * @return R
     */
    @ExceptionHandler({BindException.class})
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ResultMsg bindExceptionHandler(BindException exception) {
        List<FieldError> fieldErrors = exception.getBindingResult().getFieldErrors();
        log.warn("参数绑定异常,ex = {}", fieldErrors.get(0).getDefaultMessage());
        return ResultMsg.resultFail(fieldErrors.get(0).getDefaultMessage());
    }

}
